package com.central.comment.service.serviceImp

import cn.hutool.core.bean.BeanUtil
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.central.comment.mapper.CommentMapper
import com.central.comment.mq.CommentSink
import com.central.comment.mq.sendIntegralMes
import com.central.comment.mq.sendWxSubscribe
import com.central.comment.pojo.comment.CommentDto
import com.central.comment.service.CommentService
import com.central.common.entity.Comment
import com.central.common.enum.CommentTypeEnum
import com.central.common.enum.LikeTypeEnum
import com.central.common.feign.LikeService
import com.central.common.feign.UserService
import com.central.common.model.*
import com.central.common.service.impl.SuperServiceImpl
import com.central.common.utils.format
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.util.concurrent.CompletableFuture

/**
 * @author  fly
 * @date  2021/5/26 14:53
 * @version 1.0
 */
@Service
open class CommentServiceImp : SuperServiceImpl<CommentMapper, Comment>(), CommentService {


    @Autowired
    private lateinit var userService: UserService

    @Autowired
    private lateinit var likeService: LikeService

    @Autowired
    private lateinit var commentSink: CommentSink

    override fun insertComment(commentDto: CommentDto, sysUser: SysUser): CommonResult<Boolean> {

        val comment = Comment()
        return save(comment.apply {
            BeanUtil.copyProperties(commentDto, this)
            topId = commentDto.pid?.run { getById(this)
                ?.run { topId.takeIf { it != 0L } ?.run { this } ?: commentDto.pid } ?: 0 } ?: 0
            createBy = sysUser.id
        }).takeIf { it }?.run {
                CompletableFuture.runAsync {
                    commentSink.sendIntegralMes(comment, null)
                }
            commentDto.pid?.let {
                CompletableFuture.runAsync {
                    commentSink.sendWxSubscribe(CommentReplyPushParam().apply {
                        userId = sysUser.id
                        userName = sysUser.username
                        content = commentDto.content
                        replyTime = comment.createTime.format()
                        getById(it)?.let {
                            openId = userService.selectByUserId(it.createBy)?.openId
                            originalContent = it.content
                        }
                    }, null)
                }.join()
            }
            success(true, "添加评论成功")
        } ?: failed("添加评论失败")
    }

    override fun removeComment(ids: String): CommonResult<Boolean> = success(
        removeByIds(ids.split(","))
    , "移除评论成功")

    override fun getCommentVoListByRelevanceId(relevanceId: Long, sysUser: SysUser, pageVo: PageVo, commentTypeEnum: CommentTypeEnum): Page<CommentVo>? = page(
        Page(pageVo.pageNumber!!, pageVo.pageSize!!), KtQueryWrapper(Comment::class.java)
            .eq(Comment::topId, 0L)
            .eq(Comment::relevanceId, relevanceId)
            .eq(Comment::type, commentTypeEnum.code)
            .orderByAsc(Comment::createTime)
    ).run {
        log.debug("当前获取的查询结果 ${this.records}")
        records.takeIf { it.isNotEmpty() }?.let {
            Page<CommentVo>(current, size, total, isSearchCount).apply {
                records = it.mapNotNull { CommentVo().apply {
                    topCommentVo = getCommentTopDetail(it.id, sysUser)
                    CommentReply = getSecondCommentIdList(it.id)?.run {
                        mapNotNull { getCommentSecondDetail(it, sysUser) }
                    }
                } }
            }
        }
    }

    override fun getCommentNumByRelevanceId(relevanceId: Long, commentTypeEnum: CommentTypeEnum): Long = count(KtQueryWrapper(Comment::class.java)
        .eq(Comment::relevanceId, relevanceId)
        .eq(Comment::type, commentTypeEnum.code))
        .toLong()

    override fun getCommentVoListByUserId(userId: Long, commentTypeEnum: CommentTypeEnum): List<Comment>? =
        list(KtQueryWrapper(Comment::class.java).eq(Comment::type, commentTypeEnum.code)
            .eq(Comment::createBy, userId)
            .orderByDesc(Comment::createTime)).takeIf { it.isNotEmpty() }

    override fun getCommentAllUserIds(commentTypeEnum: CommentTypeEnum, pageVo: PageVo): Page<Long>? =
        page(Page(pageVo.pageNumber!!, pageVo.pageSize!!), KtQueryWrapper(Comment::class.java)
            .eq(Comment::type, commentTypeEnum.code).orderByDesc(Comment::createTime)
        ).run {
            records.takeIf { it.isNotEmpty() }?.let {
                Page<Long>(current, size, total, isSearchCount).apply {
                    records = it.mapNotNull { it.createBy }.distinct()
                }
            }
        }

    override fun insertComment(commentRpcDto: CommentRpcDto): Comment? {

        val comment = Comment()
        return save(comment.apply { BeanUtil.copyProperties(commentRpcDto, this) }).takeIf { it }?.run { comment }
    }


    private fun getCommentTopDetail(id: Long, sysUser: SysUser): TopCommentVo? = getById(id)?.let {
        TopCommentVo().apply {
            userService.selectByUserId(it.createBy)?.let {
                userId = it.id
                userAvatar = it.headImgUrl
                userName = it.username
            }
            myComment = sysUser.id == it.createBy
            likeNum = likeService.getLikeNum(id, LikeTypeEnum.COMMENT).likeNum?.toLong()
            replyTime = it.createTime.format()
            BeanUtil.copyProperties(it, this)
        }
    }

    override fun getCommentByContentAndUserIdAndTypeAndRelevanceId(
        content: String,
        userId: Long,
        commentTypeEnum: CommentTypeEnum,
        relevanceId: Long
    ): Comment? = getOne(KtQueryWrapper(Comment::class.java)
        .eq(Comment::type, commentTypeEnum.code)
        .like(Comment::content, content)
        .eq(Comment::createBy, userId)
        .eq(Comment::relevanceId, relevanceId))

    private fun getCommentSecondDetail(id: Long, sysUser: SysUser): CommentSecondVo? = getCommentTopDetail(id, sysUser)?.let {
        CommentSecondVo().apply {
            userService.selectByUserId(getCommentTopUser(id))?.let {
                replyUserId = it.id
                replyAvatar = it.headImgUrl
                replyUserName = it.username
            }
            BeanUtil.copyProperties(it, this)
        }
    }

    private fun getCommentTopUser(id: Long): Long? = getById(id)?.run {
        getById(topId)?.createBy
    }

    private fun getSecondCommentIdList(pid: Long): List<Long>? = list(KtQueryWrapper(Comment::class.java)
        .eq(Comment::pid, pid)).takeIf { it.isNotEmpty() }?.run { mapNotNull { it.id } }

}
